package com.fpinjava.common;

import java.util.function.Function;

import static com.fpinjava.common.TailCall.ret;
import static com.fpinjava.common.TailCall.sus;

public abstract class List<A> {
    protected abstract A head();

    protected abstract List<A> tail();

    protected abstract List<A> take(int n);

    protected abstract boolean isEmpty();

    public abstract List<A> setHead(A h);

    public abstract List<A> drop(int n);

    public abstract List<A> dropWhile(Function<A, Boolean> f);

    public abstract List<A> reverse();

    public abstract List<A> init();

    public abstract int length();


    public abstract <B> B foldLeft(B identity, Function<B, Function<A, B>> f);

    public abstract <B> Tuple<B, List<A>> foldLeft(B identity, B zero, Function<B, Function<A, B>> f);

    public abstract <B> B foldRight(B identity, Function<A, Function<B, B>> f);

    public abstract A reduce(Function<A, Function<A, A>> f);

    public abstract Result<A> headOption();


}
